package indi.zhifa.recipe.bailan.framework.auth.filter;

import indi.zhifa.recipe.bailan.framework.auth.entity.BaseTokenObject;
import indi.zhifa.recipe.bailan.framework.auth.entity.annotations.PasswordExpireAuth;
import indi.zhifa.recipe.bailan.framework.auth.entity.exception.AuthException;
import indi.zhifa.recipe.bailan.framework.auth.property.TokenConfig;
import indi.zhifa.recipe.bailan.framework.auth.util.IBaseTokenUtil;
import indi.zhifa.recipe.bailan.framework.common.entity.annotations.UnLogin;
import indi.zhifa.recipe.bailan.framework.common.entity.exception.ServiceException;
import indi.zhifa.recipe.bailan.framework.web.common.filter.BaseInterceptor;
import indi.zhifa.recipe.bailan.framework.web.common.util.ZFHttpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;

/**
 * Description: 
 * @Copyright: Copyright (c) 2020-2028 北京华咨电力科技发展有限公司 All rights reserved.
 * @author: 褚智勇(hataksumo@163.com)
 * @date:  2022/4/19 10:28
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class LoginInterceptor extends BaseInterceptor implements HandlerInterceptor {
    final IBaseTokenUtil mTokenUtil;
    final TokenConfig mTokenConfig;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws AuthException {
        if(hasAnnotations(handler, UnLogin.class)){
            return true;
        }
        String clientTokenKey = mTokenConfig.getJwtConfig().getClientTokenKey();
        String token = request.getHeader(clientTokenKey);
        if(!StringUtils.hasText(token)){
            token = request.getParameter(clientTokenKey);
            if(!StringUtils.hasLength(token)){
                outputError(response,HttpStatus.UNAUTHORIZED.value(),"token 为空，请登录！");
                return false;
            }
        }

        String tokenPrefix = mTokenConfig.getJwtConfig().getPrefix();
        int prefixIdx = token.indexOf(tokenPrefix);
        if(prefixIdx == 0){
            token = token.substring(tokenPrefix.length());
        }
        BaseTokenObject tokenObject = parseToken(request,response,handler,token);
        if(null == tokenObject){
            return false;
        }
        if(LocalDateTime.now().isAfter(tokenObject.getPasswdExpireTime())){
            if(hasAnnotations(handler, PasswordExpireAuth.class)){
                return true;
            }else{
                outputError(response,HttpStatus.UNAUTHORIZED.value(),"密码过期");
                return false;
            }
        }else{
            return true;
        }
    }

    protected BaseTokenObject parseToken(HttpServletRequest request, HttpServletResponse response, Object handler, String pToken){
        try{
            BaseTokenObject tokenObject = mTokenUtil.parseToken(pToken);
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if(null != servletRequestAttributes){
                String ip = ZFHttpUtil.getRemoteIp();
                tokenObject.setRemoteIp(ip);
            }
            mTokenUtil.putTokenIntoAttribute(tokenObject);
            return tokenObject;
        }
        catch (AuthException ex){
            outputError(response,ex.getCode(),ex.getMsg());
            return null;
        }
        catch (ServiceException ex){
            outputError(response,ex.getCode(),ex.getMsg());
            return null;
        }
        catch (Exception ex){
            outputError(response,ex.getMessage());
            return null;
        }
    }
}
